# -*- coding: UTF-8 -*-
'''
@Project ：push_rk
@File ：app.py
@IDE ：PyCharm
@Author ：苦瓜
@Date ：2025/10/13 8:36
@Note: Something beautiful is about to happen !
'''
import os.path

from flask import Flask, render_template, request
from keras.src.utils import load_img, img_to_array
from model import MyLeNet5

app = Flask(__name__)

model = MyLeNet5()
model.build(input_shape=(None, 32, 32, 3))
model.load_weights("model.weights.h5")

cls_dict = {
    0:"apple（苹果）",
    1:"baby（婴儿）",
    2:"snail（蜗牛）",
    3:"telephone（电话）"
}

# 1)	首页展示：
# 应用有一个根路由"/"，它渲染一个名为home.html的模板，作为应用的首页。
@app.route("/")
def home():
    return render_template("home.html")


# 2)	图像上传与预测：
# 用户可以通过POST请求在"/predict"路由上传图像。
@app.route("/predict", methods=["POST"])
def predict():
    try:
        if request.method == "POST":
            file_in = request.files['file']
            if not file_in:
                return render_template("error.html", msg="file_in  不能为空")
            img_list = ["jpg", 'png', 'JPEG', 'PNG']
            if file_in.filename.split(".")[-1] not in img_list:
                return render_template("error.html", msg="请按照指定格式上传图片！")
            # 获取图片路径
            path_ = os.path.join("static/images", file_in.filename)
            file_in.save(path_)  # 保存图片
            if os.path.getsize(path_) > 1024 * 1024 * 5:
                os.remove(path_)
                return render_template("error.html", msg="请修正图片大小，不得超过5MB！")
            # 图片处理
            img = read_image(path_)
            # 预测图片
            y_pred_index = model.predict(img).argmax()
            return render_template('predict.html', user_image=path_, product=cls_dict[y_pred_index])
        else:
            return render_template("predict.html")
    except Exception as e:
        return render_template("error.html", msg=f"{e}")


# 上传的图像会被保存到服务器的static/images目录下。
# 应用会读取上传的图像，使用预训练的LeNet-5模型（基于CIFAR-100数据集）进行预测。
# 预测结果（图像所属的类别）会显示在predict.html模板中。
# 3)	图像格式与大小：
# 上传的图像需要是Keras的load_img函数能够处理的格式（如JPEG, PNG等）。
# 图像在被模型处理前会被调整到32x32像素。
def read_image(path_):
    img = load_img(path_, color_mode='rgb', target_size=(-1, 32, 32, 3))
    img = img_to_array(img) / 255.  # 归一化
    return img
# 4)	模型权重：
# 应用依赖模型权重文件，该文件需要在应用启动前被放置在适当的目录中。
# 模型权重文件必须与LeNet-5架构兼容，且是基于CIFAR-100数据集训练的。
# 5)	类别字典：
# 预测结果通过类别字典映射到具体的类别名称，类别字典中的键必须与模型输出的类别索引对应。
# 6)	文件保存路径：
# 上传的图像会被保存到static/目录下，需要确保该目录在应用运行前已经存在，且应用有权限写入。
# 7)	错误处理：
# 在图像上传、保存、读取或预测过程中可能会发生异常，需要适当的错误处理机制来捕获并处理这些异常，以避免应用崩溃。
# 8)	依赖库：
# 应用依赖于Flask、Keras、NumPy等Python库，需要确保这些库在应用运行前已经被正确安装。
# 9)	安全性：
# 需要考虑上传文件的安全性，如检查文件类型、大小等，以防止恶意文件上传。
# 需要考虑模型预测的安全性，如防止对模型进行恶意攻击。
# 10)	服务器配置：
# 应用运行在Flask的开发服务器上，需要考虑生产环境下的性能、安全性和稳定性等问题。
# 需要配置服务器的IP地址和端口号，以确保应用能够被正确访问。
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=6008, debug=True)
